import { TableInstance } from '@arco-design/web-vue';

import TableWrap from '@/components/table-wrap/index.vue';
import { listenerRouteFromChange } from '@/utils/route-listener';

type PageListType = PageList | any[];
interface UseTableConfig {
  /**
   * 是否初始化的时候请求一次
   */
  immediate?: boolean;
  fetchDataApi: (pageParams: Pagination) => Promise<PageListType>;
  fetchDelApi?: () => Promise<boolean>;
  pagination?: Pagination;
}

export const useTable = (config: UseTableConfig) => {
  const { immediate = true } = config;
  const loading = ref(false);
  const defaultPaging: Pagination = {
    pageNo: 1,
    pageSize: 10,
    showPageSize: true,
    showTotal: true,
    current: 1,
    ...config.pagination,
  };

  const fromPageNo = ref();
  const dataList = ref<any[]>();
  const pagination = ref<Pagination>(defaultPaging);
  const pageParams = computed(() => {
    return {
      pageNo: pagination.value.pageNo,
      pageSize: pagination.value.pageSize,
    };
  });

  // Table实例
  const tableRef = ref<ComponentRef<typeof TableWrap>>();

  // ElTable实例
  const aTableRef = ref<TableInstance>();

  const register = (
    ref: ComponentRef<typeof TableWrap>,
    arcoRef: TableInstance
  ) => {
    tableRef.value = ref;
    aTableRef.value = unref(arcoRef);
  };

  const getTable = async () => {
    await nextTick();
    const table = unref(tableRef);
    if (!table) {
      console.error(
        'The table is not registered. Please use the register method to register'
      );
    }
    return table;
  };

  onMounted(() => {
    if (immediate) {
      if (fromPageNo.value && fromPageNo.value > 0) {
        pagination.value.pageNo = fromPageNo.value;
      }
      methods.getList();
    }
  });

  listenerRouteFromChange((route) => {
    if (route?.query?.pageNo && history.state?.forward) {
      fromPageNo.value = Number(route.query.pageNo);
    }
  });

  const methods = {
    /**
     * 获取表单数据
     */
    getList: async (keepPageNo = true) => {
      loading.value = true;
      try {
        if (!keepPageNo) {
          pagination.value.pageNo = 1;
        }
        const res = await config?.fetchDataApi(pageParams.value);
        if (typeof res === 'object') {
          if ('pagination' in res) {
            dataList.value = res.list;
            pagination.value.current = res.pagination.pageNo;
            pagination.value.total = res.pagination.total;
            pagination.value.recordTotal = res.pagination.total;
          } else {
            dataList.value = res;
          }
        } else {
          dataList.value = [];
        }
      } catch (err) {
        console.log('fetchDataApi error', err);
      } finally {
        loading.value = false;
      }
    },

    refresh: () => {
      methods.getList(false);
    },

    // 删除数据
    delList: async (idsLength: number, confirm = true) => {
      const { fetchDelApi } = config;
      if (!fetchDelApi) {
        console.warn('fetchDelApi is undefined');
        return;
      }
      if (confirm) {
        MessageInfo.confirm('确认删除该数据?', async () => {
          const res = await fetchDelApi();
          if (res) {
            MessageInfo.success('删除成功');
            // 计算出临界点
            pagination.value.pageNo =
              (pagination.value.total ?? 0) %
                (pagination.value.pageSize ?? 1) ===
                idsLength || (pagination.value.pageSize ?? 1) === 1
                ? (pagination.value.pageNo ?? 0) > 1
                  ? (pagination.value.pageNo ?? 0) - 1
                  : pagination.value.pageNo ?? 0
                : pagination.value.pageNo ?? 0;
            methods.getList();
          }
        });
      } else {
        const res = await fetchDelApi();
        if (res) {
          MessageInfo.success('删除成功');
          // 计算出临界点
          pagination.value.pageNo =
            (pagination.value.total ?? 0) % (pagination.value.pageSize ?? 1) ===
              idsLength || (pagination.value.pageSize ?? 1) === 1
              ? (pagination.value.pageNo ?? 0) > 1
                ? (pagination.value.pageNo ?? 0) - 1
                : pagination.value.pageNo ?? 0
              : pagination.value.pageNo ?? 0;
          methods.getList();
        }
      }
    },
    getRowIndex: (rowIndex: number) => {
      return (
        rowIndex +
        1 +
        ((pagination.value.current || 1) - 1) *
          (pagination.value.pageSize || 10)
      );
    },
    getSelectionData: async () => {
      const table = await getTable();
      return table?.getSelectionData();
    },
    expandAll: async (checked: boolean) => {
      const table = await getTable();
      table?.tableRef?.expandAll(checked);
    },
    getSelectionDataKey: async () => {
      const table = await getTable();
      return table?.getSelectionDataKey();
    },
  };

  pagination.value.onChange = (pageNo: number) => {
    pagination.value.pageNo = pageNo;
    methods.getList();
  };

  pagination.value.onPageSizeChange = (pageSize: number) => {
    pagination.value.pageSize = pageSize;
    methods.getList(false);
  };

  return {
    tableRegister: register,
    tableMethods: methods,
    tableState: {
      pageParams,
      pagination,
      dataList,
      loading,
    },
  };
};
